package com.keson.guard.util;

import android.os.Environment;
import android.util.DisplayMetrics;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.keson.guard.MainActivity;
import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadListener;
import com.liulishuo.filedownloader.FileDownloader;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class MqttClientUtil {
	private static MqttClient sampleClient;
	private static int i = 1;

	public static MqttClient getInstance() {
		if(sampleClient==null) {
			try {
				File infoFile = new File(Environment.getExternalStorageDirectory().toString()+"/info.properties");
				FileReader is = null;
				BufferedReader br = null;

				String cfg = "";
				try {
					is = new FileReader(infoFile);
					br = new BufferedReader(is);
                    cfg = br.readLine();

				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				String clientId = cfg.substring(cfg.indexOf("\"clientNo\":\"")+"\"clientNo\":\"".length());
				clientId = clientId.substring(0,clientId.indexOf("\",\""));

				System.out.println(clientId+"guard"+Math.random());
				sampleClient = new MqttClient("tcp://47.94.80.3:61613", clientId+"guard"+Math.random(), new MemoryPersistence());
//				sampleClient = new MqttClient("tcp://192.168.0.32:61613", clientId+"guard", new MemoryPersistence());

				final MqttConnectOptions connOpts = new MqttConnectOptions();
				connOpts.setUserName("admin");
				connOpts.setPassword("keson-123".toCharArray());
				connOpts.setCleanSession(true);
				//connOpts.setAutomaticReconnect(true);
				final String finalClientId = clientId;
				sampleClient.setCallback(new MqttCallback() {

					@Override
					public void messageArrived(String topic, MqttMessage message) throws Exception {
						// TODO Auto-generated method stub
						// TODO Auto-generated method stub
						String msg = AESUtil.decrypt(message.getPayload());
						JSONObject info = null;
						try {
							info  = JSONObject.parseObject(msg);
						} catch (Exception e) {
							e.printStackTrace();
						}
//						操作
						if(topic.equals("guard")) {
							String todo = info.getString("todo");
							JSONArray clients = info.getJSONArray("clients");
							if(clients.contains(finalClientId)) {
								System.out.println("todo "+ todo);
								switch (todo) {
									case "resetApp":
										CmdUtil.execRootCmd("pm uninstall com.keson.eq");
										break;
									case "resetConfig":
                                        new Thread(new Runnable() {
											@Override
											public void run() {
												try {
													DownLoadUtil.downLoadFromUrl("http://47.94.80.3:8080/update/info.properties","info.properties", Environment.getExternalStorageDirectory().toString());
													DownLoadUtil.downLoadFromUrl("http://47.94.80.3:8080/update/config.properties","config.properties", Environment.getExternalStorageDirectory().toString());
													DownLoadUtil.downLoadFromUrl("http://47.94.80.3:8080/update/centerConfig.properties","centerConfig.properties", Environment.getExternalStorageDirectory().toString());
												} catch (IOException e) {
													e.printStackTrace();
												}
												CmdUtil.execRootCmd("am force-stop com.keson.eq");
												CmdUtil.execRootCmd("am start -n com.keson.eq/.StartActivity");
											}
										}).start();
										break;
									case "startVpn":
										if(!new File(Environment.getExternalStorageDirectory() + "/.000/client1.ovpn").exists()){
											String url = "http://47.94.80.3:8080/update/client1.ovpn";
											String fileName = "client1.ovpn";
											String mSavePath = Environment.getExternalStorageDirectory().toString() + "/.000";
											BaseDownloadTask task = FileDownloader.getImpl().create(url);
											task.setPath(mSavePath+"/"+fileName)
													.setForceReDownload(true)
													.setListener(new FileDownloadListener(){
														@Override
														protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {

														}

														@Override
														protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
															System.out.println("正在下载 "+soFarBytes+"/"+totalBytes+"  "+task.getSpeed()+"kb/s");
														}

														@Override
														protected void completed(BaseDownloadTask task) {
															System.out.println("vpn配置下载完毕");
														}

														@Override
														protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {

														}

														@Override
														protected void error(BaseDownloadTask task, Throwable e) {
															System.out.println("错误，10秒后重新尝试下载");
															try {
																Thread.sleep(10000);
															} catch (InterruptedException e1) {
																e1.printStackTrace();
															}
															task.reuse();
															task.start();
														}

														@Override
														protected void warn(BaseDownloadTask task) {

														}
													}).start();
										}
										if(!UICheckUtil.isApkInstalled(MainActivity.main,"de.blinkt.openvpn")){
											String url = "http://47.94.80.3:8080/update/de.blinkt.openvpn_168.apk";
											String fileName = "de.blinkt.openvpn_168.apk";
											String mSavePath = Environment.getExternalStorageDirectory().toString() + "/Download";
											BaseDownloadTask task = FileDownloader.getImpl().create(url);
											task.setPath(mSavePath+"/"+fileName)
													.setForceReDownload(true)
													.setListener(new FileDownloadListener(){
														@Override
														protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {

														}

														@Override
														protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
															System.out.println("正在下载 "+soFarBytes+"/"+totalBytes+"  "+task.getSpeed()+"kb/s");
														}

														@Override
														protected void completed(BaseDownloadTask task) {
															System.out.println("vpn软件下载完毕");
															CmdUtil.execRootCmd("pm install -r " + Environment.getExternalStorageDirectory().toString()+"/Download/de.blinkt.openvpn_168.apk");
															startVpn();
														}

														@Override
														protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {

														}

														@Override
														protected void error(BaseDownloadTask task, Throwable e) {
															System.out.println("错误，10秒后重新尝试下载");
															try {
																Thread.sleep(10000);
															} catch (InterruptedException e1) {
																e1.printStackTrace();
															}
															task.reuse();
															task.start();
														}

														@Override
														protected void warn(BaseDownloadTask task) {

														}
													}).start();
										}else{
											startVpn();
										}

										break;
									case "stopVpn":
										CmdUtil.execRootCmd("am force-stop de.blinkt.openvpn");
										Cache.isSetting = false;
										break;
									case "terminal":
										try {
											System.out.println("远程操作 terminal");
											if(info.getString("cmd").indexOf("download")>-1){
												String url = info.getString("cmd").split("download ")[1];
												String fileName = url.split("/")[url.split("/").length-1];
												String mSavePath = Environment.getExternalStorageDirectory().toString()+"/Download/";
												BaseDownloadTask task = FileDownloader.getImpl().create(url);
												final JSONObject obj4 = new JSONObject();
												obj4.put("clientNo", finalClientId);
												obj4.put("todo", "terminalResult");
												task.setPath(mSavePath+"/"+fileName)
														.setForceReDownload(true)
														.setListener(new FileDownloadListener(){
															@Override
															protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {

															}

															@Override
															protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
																obj4.put("result", "正在下载 "+soFarBytes+"/"+totalBytes+"  "+task.getSpeed()+"kb/s");
																publishTopic("action", 2, obj4.toJSONString(),false);
															}

															@Override
															protected void completed(BaseDownloadTask task) {
																obj4.put("result", "下载完毕");
																publishTopic("action", 2, obj4.toJSONString(),false);
															}

															@Override
															protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {

															}

															@Override
															protected void error(BaseDownloadTask task, Throwable e) {
																obj4.put("result", "错误，10秒后重新尝试下载");
																publishTopic("action", 2, obj4.toJSONString(),false);
																try {
																	Thread.sleep(10000);
																} catch (InterruptedException e1) {
																	e1.printStackTrace();
																}
																task.reuse();
																task.start();
															}

															@Override
															protected void warn(BaseDownloadTask task) {

															}
														}).start();
											}else{
												JSONObject obj4 = new JSONObject();
												obj4.put("clientNo", finalClientId);
												obj4.put("todo", "terminalResult");
												obj4.put("result", CmdUtil.execRootCmd(info.getString("cmd")));
												publishTopic("action", 2, obj4.toJSONString(),false);
											}
										} catch (Exception e) {
											e.printStackTrace();
										}
										break;
									default:
										break;
								}
							}
						}
					}

					@Override
					public void deliveryComplete(IMqttDeliveryToken token) {
						// TODO Auto-generated method stub
						if(token.isComplete()) {
//							StatusUI.setStatus("在线");
						}
					}

					@Override
					public void connectionLost(Throwable cause) {
						// TODO Auto-generated method stub
						System.out.println("离线");
						cause.printStackTrace();
						while (true){
							try {//如果没有发生异常说明连接成功，如果发生异常，则死循环
								Thread.sleep(10000);
								if(!sampleClient.isConnected()) {
									sampleClient.connect(connOpts);
								}else {
									MqttClientUtil.subscribeTopic("guard", 2);
									break;
								}
							}catch (Exception e){
								continue;
							}
						}
					}
				});
				sampleClient.connect(connOpts);
				//StatusUI.setStatus("在线");
			} catch (MqttException me) {

				try {
					Thread.sleep(5000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				//StatusUI.setStatus("离线");

				if(true/*i<=5*/) {
					i++;
					try {
//						sampleClient = null;
						MqttClientUtil.getInstance();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return sampleClient;
	}

	public static void publishTopic(String topic, int qos, String content, boolean retained) {
		MqttClient sampleClient = MqttClientUtil.getInstance();
		System.out.println("MQTT 发布主题"+topic);
		System.out.println("MQTT 正在发布消息"+content);
		content = AESUtil.encrypt(content);
		MqttMessage message = new MqttMessage(content.getBytes());
		message.setQos(qos);
		message.setRetained(retained);
		try {
			sampleClient.publish(topic, message);
		} catch (MqttPersistenceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//StatusUI.setStatus("离线");
		} catch (MqttException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//StatusUI.setStatus("离线");
		}
		System.out.println("MQTT 消息发布成功");
	}

	public static void subscribeTopic(String topic, int qos) {
		MqttClient sampleClient = MqttClientUtil.getInstance();
		try {
			sampleClient.subscribe(topic,qos);
			//StatusUI.setStatus("在线");
		} catch (MqttPersistenceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//StatusUI.setStatus("离线");
		} catch (MqttException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//StatusUI.setStatus("离线");
		}
	}

	private static float getDpi() {
		DisplayMetrics dm = new DisplayMetrics();
		MainActivity.main.getWindowManager().getDefaultDisplay().getMetrics(dm);
		return dm.densityDpi;
	}

	private static void startVpn(){
		Cache.isSetting = true;
		CmdUtil.execRootCmd("am force-stop com.keson.eq");
		CmdUtil.execRootCmd("am start -n de.blinkt.openvpn/.activities.MainActivity");
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("dpi "+getDpi());
		try{
			if(getDpi()==160){
				CmdUtil.execRootCmd("input tap 952 35");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 39 33");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 90 213");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 70 104");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 100 166");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 1050 36");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 260 147");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 870 1023");
			}else{
				CmdUtil.execRootCmd("input tap 891 54");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 54 48");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 150 321");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 114 156");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 147 246");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 1035 53");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 309 216");
				Thread.sleep(2000);
				CmdUtil.execRootCmd("input tap 885 1071");
			}
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(30*60*1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				CmdUtil.execRootCmd("am force-stop de.blinkt.openvpn");
			}
		}).start();
		Cache.isSetting = false;
	}

}
